//
// RS Game Framework
// Copyright © 2009 Jedd Haberstro
// jhaberstro@gmail.com
// 
// $Id:
//

#ifndef RS_LOCKFREEFREELIST_HPP
#define RS_LOCKFREEFREELIST_HPP

#include "rs/LockFreeStack.hpp"

namespace rs
{
    namespace concurrency
    {
        template< typename T >
        class LockFreeFreeList
        {
        private:
            
            typedef LockFreeStack< T > ObjectStack;
            typedef typename ObjectStack::Cell Cell;
            
        public:
            
            explicit LockFreeFreeList(UInt32 numObjects);
            
            ~LockFreeFreeList();
            
            void* AllocateInstance();
            
            template< typename U >
            T* AllocateInstance(U param);
            
            void DeleteInstance(T* instance);
            
        private:
            
            ObjectStack stack_;
            Cell* objects_;
            UInt32 const size_; 
        };
        
        
        template< typename T >
        inline LockFreeFreeList< T >::LockFreeFreeList(UInt32 numObjects)
        : size_(numObjects) {
            objects_ = operator new(sizeof(Cell) * numObjects);
            for (int i = 0; i < numObjects; ++i) {
                stack_.Push(&objects_[i]);
            }
        }
        
        template< typename T >
        inline LockFreeFreeList< T >::~LockFreeFreeList() {
            operator delete(objects_);
        }
        
        template< typename T >
        inline void* LockFreeFreeList< T >::AllocateInstance() {
            Cell* instance = stack_.Pop();
            return new(&instance->value) T;
        }
        
        template< typename T >
        template< typename U >
        inline T* LockFreeFreeList< T >::AllocateInstance(U param) {
            Cell* instance = stack_.Pop();
            return new(&instance->value) T(param);
        }
        
        template< typename T >
        inline void LockFreeFreeList< T >::DeleteInstance(T* instance) {
            instance->~T();
            stack_.Push(reinterpret_cast< Cell* >(instance));
        }
    }
}

#endif // RS_LOCKFREEFREELIST_HPP
